package com.sunny.zkbase;

import org.apache.zookeeper.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.zookeeper.data.Stat;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class ZkClient {

    private static final String HOST = "127.0.0.1";
    private static final int PORT = 2181;
    private Logger log = LoggerFactory.getLogger(ZkClient.class);

    private ZooKeeper zk;
    private CountDownLatch countDownLatch = new CountDownLatch(1);
    private String host;
    private int port;

    public ZkClient(String host, int port) {
        this.host = host;
        this.port = port;
    }

    /**
     * 连接服务器
     */
    public void start() throws IOException {

        log.info("正在连接中...");
        zk = new ZooKeeper(host + ":" + port, 20000, watchedEvent -> {
            log.info("process ", watchedEvent);
            if (watchedEvent.getState() ==
                    Watcher.Event.KeeperState.SyncConnected) {
                countDownLatch.countDown();
            }
        });
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("state is {}", zk.getState());
        log.info("zk session begin");

    }

    public void syncCreateNode(String path, String value) throws KeeperException, InterruptedException {
        log.info("开始创建节点");
        String result = zk.create(path, value.getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);
        log.info("创建结果：{}",result);
    }

    public void asyncCreateNode(String path, String value){
        log.info("开始异步创建节点");
        zk.create(path, value.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL,

                (i, s, o, s1) ->{
                    Object[] obj = {i,s,o,s1};
                    log.info("创建结果为{}:{}:{}:{}",obj);
                },
                "context");
    }

    public void clear() throws KeeperException, InterruptedException {
        log.info("开始清理...");
        List<String> children = zk.getChildren("/",false);
        children.forEach(child-> {
            try {
                zk.delete("/" + child, -1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (KeeperException e) {
                e.printStackTrace();
            }
        });
    }

    public List<String> getChildren(String path) throws KeeperException, InterruptedException {
        log.info("获取子节点...");
        List<String> children = zk.getChildren(path, watchedEvent -> log.info("子节点变化:{}",watchedEvent));
        log.info("得到子节点:{}",children);
        return children;
    }

    public String getData(String path) throws KeeperException, InterruptedException {
        log.info("准备获取数据:{}",path);
        String data = new String(zk.getData(path, false, null));
        log.info("得到数据:{}",data);
        return data;
    }

    public String asyncGetData(String path) throws KeeperException, InterruptedException {
        log.info("异步获取数据：{}",path);
        String data = new String(zk.getData(path, watchedEvent -> {
            log.info("异步获得数据回调:{}",watchedEvent);
        }, null));
        log.info("异步得到数据：{}",data);
        return data;
    }

    public void setData(String path, String value) throws KeeperException, InterruptedException {
        log.info("开始设置节点值...");
        zk.setData(path, value.getBytes(), -1);
        log.info("设置完毕");
    }

    public Stat exist(String path) throws KeeperException, InterruptedException {
        log.info("检测是否存在节点：{}",path);
        Stat stat = zk.exists(path, watchedEvent -> {
           log.info("event是：{}",watchedEvent);
        });
        log.info("得到结果是:{}",stat);
        return stat;
    }

    public void delete(String path) throws KeeperException, InterruptedException {
        log.info("删除节点开始...");
        zk.delete(path, -1);
        log.info("删除完成");
    }

    public static void main(String[] args) {

        ZkClient zkClient = new ZkClient("192.168.163.128", PORT);
        try {
            zkClient.start();
            zkClient.syncCreateNode("/aaa", "testaaa");
            zkClient.getData("/aaa");
            zkClient.exist("/aaa");
            zkClient.exist("/bbb");
            zkClient.asyncCreateNode("/bbb", "testbbb");
            zkClient.exist("/bbb");
            zkClient.delete("/bbb");
            zkClient.exist("/bbb");
            zkClient.clear();
            zkClient.exist("/aaa");
            zkClient.asyncCreateNode("/aaa","tttaaa");
            zkClient.asyncGetData("/aaa");
            zkClient.setData("/aaa","newaaa");
            zkClient.getData("/aaa");
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (KeeperException e) {
            e.printStackTrace();
        }

    }

}
